package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.common.StringToLong;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.enity.Category;
import com.itheima.reggie.enity.Dish;
import com.itheima.reggie.enity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/*
 * 菜品管理
 * */
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
    @Autowired
    DishService dishService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    DishFlavorService dishFlavorService;
    //注入RedisTemplate
    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    /**
     * 新增菜品
     *
     * @param dishDto
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto) {
        log.info(dishDto.toString());

        dishService.saveWithFlavor(dishDto);

        //清理所有菜品的缓存数据
        redisTemplate.delete("dishDto"+ dishDto.getCategoryId());

        return R.success("新增菜品成功");
    }

    /*
     * 分页查询
     * */
    @GetMapping("/page")
    public R<Page> page(Integer page, Integer pageSize, String name) {
        //1.定义page对象，设置分页参数
        //DishDto的对象
        Page<DishDto> pageDto = new Page<>();
        //Dish的对象
        Page<Dish> pageBean = new Page(page, pageSize);
        //2.定义wrapper，设置模糊查询条件  //Dish : 表示对Dish操作
        LambdaQueryWrapper<Dish> Wrapper = new LambdaQueryWrapper<>();
        //StringUtils.isNotEmpty : 进行非空判断
        Wrapper.like(StringUtils.isNotEmpty(name), Dish::getName, name);
        //3.调用mp提供的分页查询方法
        dishService.page(pageBean, Wrapper);

        //BeanUtils工具 : 实现两个对象数据的复制
        /*
         * 参数1:源对象
         * 参数2:目标数据
         * 参数3:忽略拷贝字段
         * */
        BeanUtils.copyProperties(pageBean, pageDto, "records");
        //4.重新构建dish列表对象，查询当前菜品的分类名称，封装到dishDto对象
       /* List<Dish> records = pageBean.getRecords();
        ArrayList<DishDto> dishList = new ArrayList<>();
        for (Dish dish: records) {
             //1.构建dishDto对象
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            //2.查询分类表: category，查询指定分类id对象的分类名称
            //条件构造器
            LambdaQueryWrapper<Category>  categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
            categoryLambdaQueryWrapper.eq(Category::getId,dishDto.getCategoryId());
            Category category = categoryService.getOne(categoryLambdaQueryWrapper);
            //3.将查询到categoryName封装到dishDto中
            dishDto.setCategoryName(category.getName());
            //将构建好的加进来
            dishList.add(dishDto);
        }*/
        List<DishDto> list = pageBean.getRecords().stream().map(dishItem -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dishItem, dishDto);
            Long categoryId = dishItem.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);

            if (category != null) {
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }
            return dishDto;
        }).collect(Collectors.toList());
        //设置Page<DishDTO>的records
        pageDto.setRecords(list);
        //4.返回page对象
        return R.success(pageDto);
    }

    /**
     * 根据id查询菜品信息和对应的口味信息
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<DishDto> get(@PathVariable Long id) {
        DishDto dishDto = dishService.getByIdWithFlavor(id);
        return R.success(dishDto);
    }

    /**
     * 修改菜品
     *
     * @param dishDto
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody DishDto dishDto) {
        log.info(dishDto.toString());

        dishService.updateWithFlavor(dishDto);

        Set<Object> keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);

        return R.success("修改菜品成功");
    }


    /**
     * 根据条件查询对应的菜品数据
     *
     * @param dish
     * @return
     */
    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish) {
        List<DishDto> dishDtoList1 = null;
        // 从redis中 获取指定分类下的菜品列表数据:key(dish_categoryid)
        //动态构造一个Key
        String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();//dish_1397844391040167938_1
        dishDtoList1 = (List<DishDto>) redisTemplate.opsForValue().get(key);
        /*
         * 判断是否查询到
         * */
        if (dishDtoList1 != null) {
            //如果存在这直接返回，无需查询数据库
            return R.success(dishDtoList1);
        }
        //构造查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
        //添加条件，查询状态为1（起售状态）的菜品
        queryWrapper.eq(Dish::getStatus, 1);
        //添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

        List<Dish> list = dishService.list(queryWrapper);

        List<DishDto> dishDtoList = list.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item, dishDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }

            //当前菜品的id
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DishFlavor::getDishId, dishId);
            //SQL:select * from dish_flavor where dish_id = ?
            List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
            dishDto.setFlavors(dishFlavorList);

            return dishDto;
        }).collect(Collectors.toList());
        //4.将从持久层查询的菜品列表数据，存储到redis中 , 要保持key一致
        redisTemplate.opsForValue().set(key,dishDtoList1,60, TimeUnit.MINUTES);
        return R.success(dishDtoList);
    }

    /**
     * 删除
     */
    @DeleteMapping
    public R<String> delete(String ids) {
        //调用封装好的类把String类型转化为Long类型
        List<Long> idList = StringToLong.stringToLong(ids);
        dishService.removeWithFlavor(idList); //自定义的方法
        return R.success("删除成功");
    }

    /**
     * 批量起售和停售
     *
     * @param ids    传入需要操作的id数组
     * @param status 需要变更到的状态
     * @return 返回数据联调对象R
     */
    @PostMapping("/status/{status}")
//@PathVariable: 取@requestMapping传的参数
    public R<String> updateStatus(Long[] ids, @PathVariable int status) {
        //将数组转为集合
        List<Long> idsList = Arrays.asList(ids);
        //创建更新的条件构造器
        LambdaUpdateWrapper<Dish> queryWrapper = new LambdaUpdateWrapper<>();
        //设置修改状态和条件
        queryWrapper.set(Dish::getStatus, status).in(Dish::getId, idsList);
        //执行更新操作
        dishService.update(queryWrapper);
        return R.success("操作成功！");
    }


}
